The difference between arr.append(curr) and arr.append(curr[:]) is that the first one copy the curr list address to arr and the second one copy the values of curr to arr.
Let's see the difference using examples.
First scenario:
curr = [5, 10, 15, 20]
arr = []
arr.append(curr)
print("Before update")
print("Curr: {}\nArr: {}".format(curr, arr))
curr[1] = 7
print("After update")
print("Curr: {}\nArr: {}".format(curr, arr))
Output:
Before update
Curr: [5, 10, 15, 20]
Arr: [[5, 10, 15, 20]]
After update
Curr: [5, 7, 15, 20]
Arr: [[5, 7, 15, 20]]
Second scenario:
curr = [5, 10, 15, 20]
arr = []
print("Before update")
arr.append(curr[:])
print("Curr: {}\nArr: {}".format(curr, arr))
curr[1] = 7
print("After update")
print("Curr: {}\nArr: {}".format(curr, arr))
Output:
Before update
Curr: [5, 10, 15, 20]
Arr: [[5, 10, 15, 20]]
After update
Curr: [5, 7, 15, 20]
Arr: [[5, 10, 15, 20]]
As you can see in first scenario both curr and arr is updated upon changing one index value of the curr list. Because appending the curr to arr holds the same memory address.
In second scenario only curr is updated upon changing one index value of the curr list. Because appending [:] to arr copies the contents to curr list to arr list.
According to said above(theory), the reason why you get an [[], [], [], [], [], [], [], []] when you run the code changing curr for curr[:] is because in the last line curr.pop() in backtrack function you're removing the last elements one by one so you're taking off the elements from the list which is located at same space memory all the time and not from a copy list values of it.