Нижнее подчёркивание это такое же допустимое имя переменной, как и x, например.
То есть, с точки зрения интерпретатора, выражения for _ in range(5) и for x in range(5) ничем не отличаются и будут выполнятся одинаково.
Просто по традиции нижнее подчёркивание используют для того, чтобы показать, что эта переменная нигде дальше не используется. То есть мы используем какую-то синтаксическую конструкцию, в которой требуется создать новую переменную, но нам нужна не эта переменная, а какие-то другие эффекты от данной синтаксической конструкции.
Выражение for _ in range(5) обычно используется просто для того, чтобы повторить что-то 5 раз. На каждой итерации переменная _ будет принимать последовательно значения 0, 1, 2, 3, 4, но нам эти значения не нужны, нам нужно только чтобы произошло пять итераций. Поэтому мы и даём имя переменной _, так как это традиционное обозначение ненужной переменной.
Теперь относительно того, что вообще происходит в вашем выражении. Само выражение вида [что-то for переменная in последовательность] - это так называемое списковое включение (в оригинале - list comprehension).
На самом деле оно просто представляет из себя сокращённый синтаксис такого цикла:
res = []for переменная in последовательность: res.append(что-то)
Умножение массива на число создаёт массив, в котором исходный массив повторён несколько раз. Соответственно, [0]*5 - это всего лишь краткая запись для [0, 0, 0, 0, 0]
Соответственно, с учётом вышесказанного, ваше выражение полностью эквивалентно такому коду:
matrix = []for _ in range(5): matrix.append([0, 0, 0, 0, 0])