Change new_expression.append(expression) to new_expression.append(expression[:]) can work.
The reason is that if you append expression, each element within new_expression will points to the same object. We need to raise a new object by copying.
expression = ['+', '10', 'x']
variables = {"x": (3,4)}
new_expression = []
for key, value in variables.items():
key_index = expression.index(key)
for i in range(3,5):
expression[key_index] = i
new_expression.append(expression[:])
print("new_expression", new_expression)
You may want to change for i in range(3,5): to for i in value:, as you already define the values in the variables.
Refined version:
expression_template = ['+', '10', 'x']
variables = {"x": (3,4)}
new_expression = []
for key, value in variables.items():
key_index = expression_template.index(key)
for i in value:
expression = expression_template[:]
expression[key_index] = i
new_expression.append(expression)
print("new_expression", new_expression)