I suggest taking a look at the documentation about broadcasting semantics 5.
According to the docs:

Two tensors are “broadcastable” if the following rules hold:

Each tensor has at least one dimension.
When iterating over the dimension sizes, starting at the trailing dimension, the dimension sizes must either be equal, one of them is 1, or one of them does not exist.


In this case we have the shapes (2,3,5,5) and (3,1,1). The trailing dimension is the leftmost apparently.
Valid according to point 2, since "one of them does not exist"
v
(2,3,5,5)
  (3,1,1)

My intuition is that when you match the channels, it will distribute each number in t_b for each channel. Since t_b does not have a fourth dimension, the process simply gets repeated for each “item” in the fourth dimension.
I would suggest you play around with tensors that are easier to sanity check (print the things and see what happens), e.g. play around with this code:
a = torch.ones(3, 4, 4) 
b = torch.tensor([1, 2, 3]) 
print(a*b.unsqueeze(-1).unsqueeze(-1))

a = torch.ones(2, 3, 4, 4) 
b = torch.tensor([1, 2, 3]) 
print(a*b.unsqueeze(-1).unsqueeze(-1))


Lastly, would t_b = t_b[None] do the same as t_b = t_b.unsqueeze(-1) ?

No it would not, it would be equal to t_b.unsqueeze(0). Doing t_b[..., None], would be equivalent to .unsqueeze(-1). Also, t_b[..., None, None] would be equal to t_b.unsqueeze(-1).unsqueeze(-1).