это списковое выражение (
list comprehention)
символ _ никакая ни магия, а такое же имя переменной как a или value, но с тем отличием что оно общепринятое, его используют тогда, когда надо присвоить переменной значение, но сама переменная не нужна. Пример
l = [0, 1]
a, b = l # 1
a, _ = l # 2
Представим что нужно раскрыть список и передать значения в переменные, но интересует нас только значение которое запишется в переменную a. Можно сделать как в случае 1, но тогда linter скажет что задается переменная которая не используется. В случае 2 этого не будет. Однако и в переменную a и в переменную b запишется свое значение.
То есть все это для наглядности, читаемости и удобства.
Несколько более весомые пример в питоне 3
>>> l = list(range(10))
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a, _, c = l
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 3)
>>> a, *_, c = l
>>> a, _, c
(0, [1, 2, 3, 4, 5, 6, 7, 8], 9)
Далее, запятая тоже никакая ни магия и можно записать так
new_lst = [el for (el, _) in groupby(lst)]
Что полностью удовлетворяет сигнатуре вида