What you need is some fuzzy logic.

First, Beerman's right. Computers react too quickly. Therefore, only run the AI every x frames - slow down its reactions.
Second, computers are far too precise - and this is where the fuzziness comes in. Deliberately retard its precision, so it only has a rough idea of what it's doing in a round about way.
This is easier to achieve than it sounds. As an example, I used this kind of code in my "Ping Pong" example (see attachment):
Code:
RoughY = (int(BallY / 20) * 20) + 10
Where "BallY" is where the ball actually is, and "RoughY" is the fuzzy version that the AI sees - it divides the vertical into 20 pixel high "zones" and then aims the AI at the centre of whatever "zone" the ball is in. So the AI doesn't know precisely where the ball is, only where it roughly is. Give or take 20 pixels or so.
You can, of course, change the degree of fuzziness by making the "zones" bigger or smaller. What I did in my example game is that it has a 160 pixel "zone" when the ball is in the third closest to the player - so it only knows which third of the screen (e.g. "top", "middle" or "bottom") to roughly aim for. As it gets half-way across, the precision improves to 100 pixel "zones", then 80 pixels then 25 pixels, as it reaches the CPU's bat.
Third, don't control the AI's Y coordinate directly. Control its speed (or its second derivative, in maths speak).
This also gives the game something to do in those frames when the AI ain't running. It simply continually does this every frame:
Code:
EnemyY = EnemyY + EnemyDY
Where "EnemyY" is the AI's bat Y coordinate and "EnemyDY" is the "delta" (or speed / direction) added to it every frame.
The AI does not touch its Y coordinate directly, but rather looks at its "fuzzy" view of the world (only every x frames too) and tries to work out by how much it needs to speed up / slow down the bat to get to the ball in time.
To purposefully allow for overshooting and undershooting, the speed is fuzzified too.
This time around, though, I actually work it out precisely, then make it fuzzy afterwards just before applying it to the bat - the sole reason for that is that though I want the AI to sometimes be a klutz, I don't want it to be too stupid and thus present no challenge for the player. So the fuzziness of the speed delta is only applied when it wants to move over a certain speed.
That is, when it's moving slowly, it has better speed control than when it's rushing like a madman to reach the ball on the other side of the screen - which also neatly emulates what human beings tend to do as well, as we tend to lose all our precision with the mouse when we're flinging the pointer around at a rate of knots. And, thus, the AI tends to be more likely to fuck up on exactly the kind of shots that the player will typically fuck up on - the mad dash across half the screen to get there in time.
Another real simple addition, which makes it fairer on the player (and, again, actually makes it look a bit more human) is that it only actively chases down the ball when it's coming towards the AI's bat. When the ball is heading towards the player, the AI "relaxes" and then either moves up or down a bit or roughly re-centres itself near the middle of the screen (this is chosen randomly).
The most interesting thing about this "fuzzy" approach is that the AI isn't just letting you win randomly. That's just, well, too random.
Indeed, except for the random choice of whether to re-centre itself or move up or down a bit when the ball is heading away from it, there is no randomness in the AI routine at all. It's genuinely trying to do its best at all times.
But it "fails in the gaps", so to speak.
That is, it only reacts every x frames - if the action is too fast, then it can fail in that reaction time gap. It doesn't know where things precisely are, only where they roughly are - that loss of precision creates a "gap" in which it can fail. It only has "fuzzy" control of its speed and sends it roughly at the right speed in the right direction - but not precisely so, that it can fail in the gap of its imperfect control of the bat.
And, of course, all of these impediments are exactly the impediments that humans have while playing the game too - which makes it fairer and makes the AI seem a touch more "human". Our reaction times can be a bit slow. We don't have any clue how many pixels exactly we are away from something. Even the best eye-to-hand coordination with the mouse suffers from its imprecisions.
You see, Mr.Spock was wrong. Humans are not illogical at all. We're just "fuzzy logical".

Use the mouse to move your bat. Left mouse button starts a game. Esc to quit a game in progress and also quits out of the program when on the title screen.
First to reach ten wins. Enjoy!

Edit - maybe the CPU player is a bit too stupid sometimes. Oh, well, demonstrates its capacity to fail. Just example code, and not exactly fine-tuned and well-polished (the text is not lined up symmetrically on the screen and it is possible, though rare, for the ball to get "stuck" in the bats or the side walls - I realise these things but can't be bothered to fix them).