Understanding Index w/ Cast
Why does the following query not use b.a's index?

Because the index only stores the UUID value of a, not the result of the expression a::text
To make the index eligible for use, you would need to cast the other column to the data type stored in the index, e.g.
select * 
from b 
   join c on b.a = c.a::uuid;

Note that this doesn't guarantee that the index is used, it just makes it possible.
But as the query retrieves all rows from both tables, it's highly unlikely that the index is used anyway.