So if some threads need to take an IF-branch, and some need to take an ELSE-branch, both paths are executed in sequence, with all threads in the group executing in lock-step, and a per-thread mask disabling the effects of the instructions that aren't needed for each specific thread.
If you do this enough times, with sufficiently complicated branching, you'll quickly negate any efficiency gain you get from the massive parallelism.
To simplify: Each 128 SMs can run a different program and each of their 128 "cuda cores" can do ~single-cycle (small) matrix operations.
My mental model is a bit more like you have collections of warps in a block, and all warps in a block get scheduled onto an SM. Different GPU architectures allow for different numbers of warps to be simultaneously active or inactive, and each warp has its own instruction pointer and can be suspended while waiting for things like memory. I found the picture on pg 22 here really helpful: https://images.nvidia.com/aem-dam/en-zz/Solutions/data-cente...
Note that although there's 4 schedulers, on the A100, they don't dispatch every cycle iirc.
Correct me if I'm wrong, but as far as I can tell tensor cores are just accelerators. They can't do general compute: no branch or jump.
Like you said, tensor core is similar to a special purpose ALU and is at a lower level of abstraction than something with an instruction pointer.