Here the first two inputs of the first Random component are left at their default values, which means the a single random number between 0.0 and 1.0 gets returned. It’s Seed input is driven by the loop iteration count, which means that each iteration the loop runs we are guaranteed to get a distinct random number.
Multiplying by 1000 might or might not be necessary. I just prefer to have a large seed, which probably doesn’t change anything. 
Now, we use this scaled random number as the seed of another Random component that again returns a random number that later participates in defining the random rotation angle in radians.
We only need the second Random component to get another, distinct random number, since the one from the first component is already used for another operation, but we still can use it as the seed for the next Random component, if that makes sense?
There is no true randomness at least for computers! You can imagine that if you request a random number nonetheless, the computer produces a large set of numbers and then picks one for you. Now, it needs a parameter to even know, which one to pick and that’s where the random seed comes into play. It determines which number gets picked, which means that you can fix results with the seed, since it guarantees that you always get the same random number.
If you don’t define a seed and relaunch Rhino or recompute the Grasshopper canvas, you’ll get a different result each time, and that’s because the random seed is then driven by for instance the computers internal clock, which kinda produces unique values each second, if the date is included. Each year only happens once. 
OK, since Anemone doesn’t seem to recompute the entire Grasshopper canvas, you’ll always end up with the exact same result, not a randomized one, since the seed is only set once.
Now, we change the seed inside the loop ourselves and make it dependant on the loop iteration count, which changes each time.
Still this isn’t enough, since the loop count is always the same (i.e. 0, 1, 2, 3, …), which would produce the same overall result, and this is why we also generate an x-amount of random radii outside of the loop. This guarantees that each iteration gets some extra spice and you can change the Seed of this Random component manually with a slider if you want a different result, or even write down the seeds of nice results to explore further, nonetheless being able to reinstate them later. 
Here you have to understand that we start with a point “on an already existing sphere” (i.e. D0) and a directional vector (i.e. D1) that defines the central axis and direction of a “cone” that sits with its apex (i.e. tip) on the sphere point.
From there we “copy” this directional vector by normalizing it to length one and then scaling it to a random radius - the radius of the next sphere - and using it as the z-axis of a new plane. This plane gives us an x- and y-axis to rotate around. It doesn’t matter which one we chose. The rotation is driven by a random angle which defines the apex angle and thus radius of the base of the cone. We now have a vector that now corresponds to a line on the surface of a cone (not the base surface), starting at its apex and of a random length that is equal to the random radius of the next sphere. We rotate again, this time around the original directional vector or central axis of the cone with an angle between 0 and 360° (2*Pi) to find a random next point on the cone surface that lies on a circle which is produced by cutting the cone and the end of the current vector horizontally with a plane. This point becomes the next point “on a sphere” and the randomized vector the next directional vector and so fourth.
We rotate twice to basically find a random point at a random distance on an imaginary cone. 