В строку нужно преобразовать каждый отдельный элемент кортежа. Если количество полей известно, неизменно и немногочисленно:
ptext = '{} {} {} {}'.format(
row[0].strftime('%d.%m.%Y'),
row[1].strftime('%d.%m.%Y'),
row[2],
row[3]
)
Story.append(Paragraph(ptext, styles["Normal"]))
Более универсальный вариант - обойти поля в цикле:
ptext = ''
for ndx, field in enumerate(row):
if ndx:
ptext += ' '
if isinstance(field, date):
ptext += field.strftime('%d.%m.%Y')
else:
ptext += str(field)
Story.append(Paragraph(ptext, styles["Normal"]))
В примере сознательно использован антипаттерн наращивания строки, для демонстрации этой возможности.
Или использовать включение, так будет чутка резвее и компактнее:
ptext = ' '.join(field.strftime('%d.%m.%Y') if isinstance(field, date) else str(field) for field in row)
Story.append(Paragraph(ptext, styles["Normal"]))