Start by copying some existing example code and running it locally, then edit it and see what changes. Comment pieces out, look at the results. Change magic numbers to understand the effect. It probably has some calls to a random number generator in it; add more calls to the random number generator.

(I'm mostly linking things I've done myself here, not because they're better than the alternatives, but because they're very short, and most of them run in the browser, which makes them easier to copy and edit.)

There are lots of examples bundled with Proce55ing, on Shadertoy, on bl.ocks.org, on ObservableHQ, on Jared Tarbell's website, in the Coding Train vlog, etc. My own repo of examples using Python and PyGame is at https://github.com/kragen/pyconar-talk, but I've also done examples like http://canonical.org/~kragen/sw/dev3/tweetfract with <canvas> (you have to click on the invisible <canvas> to see it) and http://canonical.org/~kragen/sw/dev3/plotiir.html. Start with small things.

There's probably some kind of awesome example repo out there for deepdream ANN stuff but I don't know what to recommend.

But that's just where to start. Once you're doing stuff you'll want to understand what you're doing and learn about more techniques (algorithmic, software design, and interfaces to libraries and devices) so you can expand your range. There's lots of resources out there (Tarbell in particular has given an hour lecture you can find on YouTube about what techniques he finds useful) but I can suggest, as techniques that give a large bang for the buck:

∙ Multiplicity with variation: many instances of the same thing that differ, for example by incrementing a variable from one instance to the next. For example, you can create 64 particles that move from point A to point B at successive points in time 30 milliseconds apart, or at the same point in time at 64 different velocities, or 64 Bezier curves from point A to point B that start at 64 angles evenly spaced across some range. http://canonical.org/~kragen/sw/dev3/curves is an example of spreading the start angles of Bezier curves over a range.

∙ Adding randomness to things. Adding randomness to pixel colors gives you "graininess"; adding randomness to object positions gives you spatial dispersion or, if the randomness varies over time, jittering; adding randomness to the angles of different objects gives you visual variety. Perlin noise and simplex noise are especially nice kinds of randomness for some purposes because they have a kind of local coherence. http://canonical.org/~kragen/sw/dev3/rectlines is an example of just drawing random rectangles and lines in random colors with alpha-blending; it's nothing special but it's a lot more interesting to look at than it would be without the randomness.

∙ Differential equations, especially over time. Real-world objects don't suddenly teleport from one position to another; if objects in your generative art do that, people will have a hard time seeing them as the same object in a new position, which may or may not be what you want. If instead you have a relatively small velocity that is added to the position each timestep, it's much easier to achieve the illusion of motion. (This is "Euler's method", and although it's suboptimal for accurate numerical integration of differential equations, generative art often doesn't care.) If the velocity itself analogously changes by adding an acceleration to it each timestep, the movement can look a lot more natural. These differences or derivatives can often be computed as linear functions of other objects. That's almost the whole deal in, for example, http://canonical.org/~kragen/sw/dev3/metacirclesky or http://canonical.org/~kragen/sw/dev3/offscreen ; in the latter, the things slow down as they move because of the line things.each(thing => {thing.Δx *= 0.998; thing.Δy *= 0.998}), which subtracts a small fraction of their velocity every time it runs. The qabbits in http://canonical.org/~kragen/sw/dev3/qabbits roam around by changing their velocity by a small random amount each timestep.

∙ Particle systems are a combination of the three previous items: a multiplicity of mostly-identical objects, with random variation from object to object, whose states evolve over time according to differential equations. http://canonical.org/~kragen/sw/dev3/spirals draws random monochrome spirals in a way inspired by Tarbell's piece "Substrate", which is basically a particle system, and the explosions in http://canonical.org/~kragen/sw/dev3/qvaders are very simple particle systems.

∙ Tiles: tesselating some space with a shape (often just a square or rectangle) and putting different images in the different tiles. That, plus randomness, is how http://canonical.org/~kragen/sw/dev3/10print.py can generate a maze with a single line of code. (It's a Python Unicode translation of a well-known one-line BASIC program for the Commodore PET from the 01970s.) This is of course how typewriters give the illusion of neat printing with a very simple mechanical system that generates pages from human keypresses.

∙ Alpha blending can go a long way to getting interesting visual effects: antialiasing, layering, translucency, glow. Also, gradients. The cheapest technique in the world is to generate a series of frames, but instead of directly displaying them, alpha-composite each new frame on top of the currently-displayed image, as in http://canonical.org/~kragen/sw/torus if you click the "Trails" checkbox, or as in http://canonical.org/~kragen/sw/dev3/loop (a poor derivative of one of Tarbell's pieces). The "curves" example I linked above uses alpha blending for antialiasing; differential equations to make the curves move smoothly; randomness to pick the control points and accelerations; and multiplicity with variation to separate the curves.

∙ Recursive subroutines; that's how http://canonical.org/~kragen/sw/dev3/tweetfract can be visually interesting inside an old-style 140-byte tweet. If you click on the canvas, anyway.

∙ Bitwise operators. These are ready to hand in most programming languages and can generate a lot of interesting variation that's right on the border between "too ordered to be interesting" and "too chaotic to be interesting". Often they are an alternative to recursion. I've written a little more about this in http://canonical.org/~kragen/bytebeat.

∙ Fractals in general, which aren't always implemented by recursive subroutines or bitwise operators, are a rich source of visually interesting material.

∙ Linear algebra is interesting in a few different ways. Scaling, rotating, and squishing a 2-D image is just matrix multiplication; moving it is just vector addition. Alpha blending is linear interpolation between colors, and Bezier curves are recursively applied linear interpolation between points. A minimal amount of linear algebra in three dimensions gives you a raytracer http://canonical.org/~kragen/sw/aspmisc/my-very-first-raytra... (using bitwise operators for quick and dirty textures) or a rasterizer (see torus example above). Convolution is linear, though a linear algebra course often doesn't teach it, and convolution gives you FIR filtering of sound including both frequency response changes and reverb, as well as image filtering (sharpen, blur, emboss, bokeh). Iterated function systems generate fractals nonrecursively as the fixpoint of the union of a small collection of affine transformations. If I'd known more about linear algebra when I wrote the "metacirclesky" guilloche generator I linked above, I could have easily fixed the cases where the point spirals off to infinity: those are just the cases where the transformation matrix has an eigenvalue greater than 1.

∙ 3-D printing and laser cutting make it easy to make generative art that isn't confined to a computer screen, though generally it's a bit more static once it's out of the machine. For example, the Sierpinski triangle cutout in http://canonical.org/~kragen/sw/laserboot/cut-6/sier.pdf (described in http://canonical.org/~kragen/sw/laserboot/cut-6/README.md.ht...) is generated from 19 lines of code (in PostScript, in sier.ps) implementing an L-system. I took the PDF to a sign shop, paid them US$17, and in ten minutes of laser cutting I got a meter-sized fractal to hang on the wall at home.

∙ Combinatorial enumeration, where you show literally every possible variation on a theme. http://canonical.org/~kragen/sw/dev3/semicirclecollages combinatorially enumerates a design space of "semicircle collages" identified by Christopher Carlson.

∙ Mathematical optimization, where you search a space that is too large to enumerate exhaustively for points that minimize some loss function. For example, http://canonical.org/~kragen/sw/81hacks/see/overnight.png is the result of using hill-climbing optimization to minimize the pixel distance from a photo by Uwe Aranas, done by http://canonical.org/~kragen/sw/81hacks/see/.

∙ Domain-specific languages. For example, http://canonical.org/~kragen/sw/dev3/trama is a DSL for generating black-and-white pixel art with bitwise and linear operators; http://canonical.org/~kragen/sw/dev3/skitch is a DSL for generating infinite patterns of alpha-blended lines with recursive subroutines; https://github.com/kragen/pytebeat is an interpreter for a small extended subset of C used as a DSL for generating PCM sounds; http://canonical.org/~kragen/sw/dev3/sweetdreams.html is a DSL embedded in C++ for generating PCM sounds; the raytracer linked above implements a very simple DSL for describing 3-D scenes;
etc.

You don't have to learn all of these! Think of them as magical items you receive one at a time on a quest, each one augmenting your powers and granting you new opportunities as you learn how to use it; don't think of them as questions that might be on the exam.