Ты не вполне понял. Во-первых, не нужно само преобразование (которое лишняя операция) в большинстве случаев. Я придумал только один юзкейс - использование кортежа как ключа словаря. Во-вторых, операция преобразования элементарна. Перемещения данных при этом не производится, память не выделяется. В твоем примере buffer += i на каждой итерации происходит выделение новой памяти и копирование в нее содержимого кортежа, что более затратно чем преобразование из списка в кортеж. Ну а добавление в конец списка, как понимаешь, тоже почти О(1). То есть по сути операции с кортежами можно сказать совсем не нужны, они безболезненно заменяются на операции со списками на небольшом наборе данных, а на большом наборе операции со списками безальтернативны ввиду в разы меньшей сложности.
Во-вторых, я не против того, что сам по себе пустой кортеж имеет право на существование. Это можно было бы реализовать вот так tuple(), но пустые скобки в питоне крайне противоречивая ситуация, потому что вот это кортеж
a = ()
a = (1)
ровно как вот это множество
d = {1}
d = {}
это какая-то очень некрасивая гнилая вишенка на торте. Когда мы в основном имеем логичный последовательный синтаксис, но вдруг на ровном месте такие кривые исключения. Для пустых значений базовых структур вполне можно было бы обойтись без минимализма и создавать объект как любой другой: list(), dict(), set(), tuple()