The IndexError and your definition of current_cache tell you what’s going on. An IndexError is most often raised when the index exceeds the number of objects in the “container” object. Here the object is the tuple caches. Higher up in the function, L is set with L = len(caches). Also, remember that python is “zero-indexed”. That is the first object in a tuple, list, dictionary, etc., is indexed by 0. To grab that one, I would use my_tuple[0], notmy_tuple[1]. With this in mind, please reconsider your choice of index value in line 40.
I think you misunderstood Ken’s previous point about how zero-based indexing works in python. If I have a list called myList that has 3 elements in it, the last one is myList[2].
Ok, have you looked at that logic? And has that cell actually been run since the last time you opened the notebook? Also you need to look at every following line that modifies grads. You need to figure out why grads is the wrong type. The first step would be to print the type right before the line that “throws”:
print(f"type(grads) = {type(grads}")
What does that show? Note that it may be correct the first time and the fail later.
This is how debugging works: you start by understanding the evidence at the point of failure. Then you need to work backwards to figure out where the actual error is. It is frequently nowhere near the point that the error is actually thrown.