An important aspect here is accessibility: By using th elements both on top and to the left with according scope attributes (col/row), screenreaders "understand" (and read/output in some way) that there are two headers for each td- one on top and one to the left. The important thing for that is not the thead element (which some browsers even add automatically if it isn't included in the original code, but which couldn't possibly be added for a column), but the th elements, which indicate header cells.
An important aspect here is accessibility: By using th elements both on top and to the left with according scope attributes (col/row), screenreaders "understand" (and read/output in some way) that there are two headers for each td- one on top and one to the left. The important thing for that is not the thead element (which some browsers even add automatically if it isn't included in the original code, but which couldn't possibly be added for a column), but the th elements, which indicate header cells.
While the <th> element defines the first row of your table as the header (e.g. via giving it a different style), the three tags <thead><tbody><tfoot> define the structure of your table. One example case is that some browsers enable scrolling of the table body independently of the header and footer.
You don't have to use any of them, it always depends on how you want your table to look and be structured.