Короткий ответ
Все три подписывают что-то, но у разных контейнеров.
Роли
label — подпись к control (input, select, textarea) через for/id или обёртку.
legend — заголовок группы внутри fieldset (набор связанных полей).
caption — название table (или иногда figure в узких контекстах; в HTML для таблицы — именно caption).
<label for="email">Email</label>
<input id="email" type="email" />
<fieldset>
<legend>Способ доставки</legend>
<label><input type="radio" name="d" /> Курьер</label>
</fieldset>
<table>
<caption>Продажи по кварталам</caption>
...
</table>
Итог
label → поле; legend → fieldset; caption → table. Не взаимозаменяемы.