Hi Matthew!
The reason we graft like you mentioned in your first sentence, is to NOT do a cross reference between the data of the two inputs.
If you look at the rectangles, the data structure is {0;0;0}(32) .....{0;0;49}(32). This means there are 49 branches, and those 49 branches have 32 rectangles each.
Now if we look at the vector input for the move component. The vectors we're inputting have a different data structure; {0;0;0;0}(1) ..... {0;0;49;31}(1). In other words 1600 individual branches (50 * 32), with 1 rectangle in them each.
If we would connect without grafting, we would cross reference the 32 rectangles with the vector, resulting in a lot of doubles. The trick is to line up the data structures either way. I choose to graft the rectangles so they would get the same structure as the vectors. We could have also used the "Shift Paths" component (does the opposite as graft), to shift the indices of the vector data structure one back, resulting into {0;0;0}(32) .....{0;0;49}(32) instead of {0;0;0;0}(1) ..... {0;0;49;31}(1).
Check out the Grasshopper 101 and 102, to get a more in depth explanation about data tree structures if this is still confusing.
Good luck!
Arie