Почему бы, действительно, не разбить? У вас же даже больше 80 символов строка получается. Это уже не по pep8, трудно читаемо - и все такое.
Ну а что касается вопроса. Получается так, что replace берет первый символ из исходной строки, а затем ищет его уже в той, в которой все символы были переведены в нижний регистр и, естественно, его там не находит в первых двух случаях.
Добавьте lower к первому аргументу replace
elem.lower().replace(elem[0].lower(), elem[0].upper(), 1)
или вообще используйте срезы
elem[0].upper() + elem[1:].lower()
а еще в Питоне есть встроенный метод
title() у строк, который делает практически то же самое.