You're not saving the variable's value inside the lambda. You're saving a variable defined outside of the lambda. It's not necessarily a global variable, but to the scope of the lambda, it is declared outside of it. When the iteration terminates, the value of i is 2. That's why when you iterate with for-loop using j, the value inside the lambda is always 2.
When you iterate on a for-loop using the i variable, you're once again changing the state of i before executing the lambda. That's why it gives you a different result.
To make the lambda get the variable's value only without keeping it dependant of any variable scope, do something like this:
a = []
for i in range(3):
    a.append((lambda k: lambda x:(k+x))(i))
lambda k: ... is used to pass the state of i to the inner lambda. It's in fact executing the function, and returning lambda x: (k+x), where k is a private variable from the lambda's scope.
Now when you try to print it using another variable, such as j, or assigning a new value to i or k:
i = 256
k = 512
for j in range(3):
    print(a[j](0))
The output is:
0
1
2